<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>Cabinet</title>
    <style>
        *{
            margin:0;
            padding:0;
            text-decoration: none;
            box-sizing: border-box;
        }
        ul,li{
            list-style: none;
            border:none;
        }
        .clear:after{
            content:"";
            display:block;
            clear:both;
        }
        body{
            overflow: hidden;
        }
    </style>
    <!-- 引入3D库-->
    <script src="js/three-v69.js"></script>
    <!-- 最新版本three -->
    <!-- <script src="js/three-v142.js"></script> -->
    <!-- 引入控制器-->
    <script src="js/OrbitControls_alter.js"></script>
    <!-- 引入动画库-->
    <script src="js/tween.min.js"></script>
</head>
<body>

<script>
    // 创建场景
    var scene;
    function createScene() {
      scene = new THREE.Scene();

      // var urls = [
      //   'assets/textures/posx.jpg',
      //   'assets/textures/negx.jpg',
      //   'assets/textures/posy.jpg',
      //   'assets/textures/negy.jpg',
      //   'assets/textures/posz.jpg',
      //   'assets/textures/negz.jpg'
      // ];
			// var cubeLoader = new THREE.CubeTextureLoader();
      // scene.background = cubeLoader.load(urls);
      
      // 在屏幕上添加坐标轴 显示坐标轴
      // scene.add(axes = new THREE.AxisHelper(100));
    }
    // createScene()

    // 创建渲染器
    var renderer;
    function createRenderer(){
        // width = document.getElementById('canvasframe').clientWidth;
        // height = document.getElementById('canvasframe').clientHeight;

        // 创建一个渲染器对象并设置大小，WebGLRenderer将会使用电脑显卡来渲染场景
        renderer = new THREE.WebGLRenderer({
          antialias:true ,// 抗锯齿:true
          // logarithmicDepthBuffer: true,
        });

        //指定渲染器的宽高（和画布框大小一致）
        renderer.setSize(window.innerWidth,window.innerHeight);
        document.body.appendChild(renderer.domElement);
        // 设置渲染器的清除色和背景透明度
        // renderer.setClearColor('#39609B');
        renderer.setClearColor('0x121A39');
        
        // //指定渲染器的宽高（和画布框大小一致）
        // renderer.setSize(width,height);
        // // 将创建的canvas元素(此处的canvas元素为three.js创建)添加到html文档中
        // document.getElementById('canvas-frame').appendChild(renderer.domElement);
        // // 设置渲染器的清除色和背景透明度
        // renderer.setClearColor('#39609B', 0.9);
    }
    // createRenderer();

    // 创建相机
    var camera;
    function createCamera(){
        // 此处设置为 透视投影相机，默认情况下，相机的上方向为Y轴，右方向为X轴，沿着Z轴垂直朝里
        // (视眼角:fov;纵横比:aspect；相机离视最近的距离:near;相机离视体积最远距离:far)
        camera = new THREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,0.1,2000);
        // 设置相机的位置坐标
        camera.position.set(0,150,300);
        // 设置相机的up方向
        camera.up.x = 0;
        camera.up.y = 1;
        camera.up.z = 0;
        // 设置相机的中心坐标
        // camera.lookAt({ 
        //   x : 0, 
        //   y : 0,
        //   z : 0 
        // });
				camera.lookAt(scene.position);// 将摄像机对准场景的中心
    }
    // createCamera();

    // 创建光源
    function createLight(){
        // 平行光源
        // 第一个参数 Hex:光的颜色 
        // 第二个参数 Intensity：光源的强度，默认是1，如果为0.5，则强度是一半，意思是颜色会淡一些
        // 第三个参数 Distance：光线的强度，从最大值衰减到0，需要的距离。 默认为0，表示光不衰减，如果非0，则表示从光源的位置到Distance的距离，光都在线性衰减。到离光源距离Distance时，光源强度为0.
        var light = new THREE.DirectionalLight(0xffffff);
        // 位置不同，方向光作用于物体的面也不同，看到的物体各个面的颜色也不一样
        light.position.set(300,400,200);//光源的向量，即光源的位置
        scene.add(light);//追加光源到场景
        // 环境光源(一般不会独自使用，一般配合着点光源或者平行光等光源使用)
        scene.add(new THREE.AmbientLight(0x444444));
    }
    // createLight();
    
    // 初始化Three
    function initThree(){
        createRenderer();
        createScene();
        createCamera();
        createLight();
    }


    // // 创建地板贴图这个纹理
    // var floorTexture;
    // function createFloorTexture(){
    //     floorTexture = THREE.ImageUtils.loadTexture('img/floor.jpg', render);
    
    //     floorTexture.wrapS = floorTexture.wrapT = THREE.RepeatWrapping;//两个方向都重复
    //     floorTexture.repeat.set(14,10);//两个方向上的重复数
    // }
    // createFloorTexture();
    // 创建地板floor
    function Floor(width=400,height=2,depth=300){
      this.x=width;
      this.y=height;
      this.z=depth;

      // 创建地板贴图这个纹理
      // var floorTexture = new THREE.TextureLoader().load('img/floor.jpg');
      var floorTexture = THREE.ImageUtils.loadTexture('img/floor.jpg', render);
      floorTexture.wrapS = floorTexture.wrapT = THREE.RepeatWrapping;//两个方向都重复
      floorTexture.repeat.set(14,10);//两个方向上的重复数


      // 创建一个三维立方体几何体
      var geometry = new THREE.BoxGeometry(this.x,this.y,this.z);
      // 创建材质(新建一个白色的，使用地板贴图这个纹理的材质)
      var material = new THREE.MeshLambertMaterial({
        // transparent: true,
        // side: THREE.DoubleSide,
        color:0xffffff,
        map:floorTexture // 使用纹理贴图为floorTexture
      });
      //网格模型对象Mesh
      var floor = new THREE.Mesh(geometry,material);
      floor.position.set(0,-this.y,0);

      /***********************以下为最新版本three v142的地板**************************/
      // var material = new THREE.MeshStandardMaterial({
      //   map: floorTexture,
      //   transparent: true,
      //   side: THREE.DoubleSide,
      // });
      // // 创建地平面并设置大小
      // var geometry = new THREE.PlaneGeometry(270, 260);
      // var floor = new THREE.Mesh(geometry, material);

      // // 设置平面位置并旋转
      // floor.rotation.x = -0.5 * Math.PI;
      // floor.position.y = -0.1;
      /***********************以上为最新版本three v142的地板**************************/

      //网格模型对象添加到场景中
      scene.add(floor);
    }
    // Floor();
    // 创建机柜上编号贴图这个纹理CanvasTexture
    function cabinetNumberTexture(str){
        var canvas = document.createElement("canvas");
        canvas.width = 50;
        canvas.height = 40;
        var ctx = canvas.getContext("2d");
        var g = ctx.createLinearGradient(0,0,50,40);
        g.addColorStop(0,"#777");
        g.addColorStop(1,"#777");
        ctx.fillStyle = g;
        ctx.fillRect(0,0,50,40);
        ctx.textBaseline='top';
        ctx.font="20px SimHei";
        ctx.fillStyle = "#00ffff";//编号颜色
        var txtWidth = ctx.measureText(str).width;
        ctx.fillText(str ,50/2-txtWidth/2,40/2-20/2);
        var texture = new THREE.Texture(canvas);
        texture.needsUpdate = true;
        return texture;
    }
    // 创建机柜
    // 构造机柜:参数（x坐标,z坐标,机柜号）
    function Cabinet(x,z,cabNmb){
        this.x=x;
        this.y=0;
        this.z=z;
        this.number = cabNmb;

        var dk = 30;//底宽
        var dc = 40;//底长

        //设置机柜的外壳
        var texture1 = THREE.ImageUtils.loadTexture('img/rack_panel.jpg', {}, render);//机柜外表贴图纹理
        var texture3 = THREE.ImageUtils.loadTexture('img/cabz.jpg', {}, render);//cabz
        var texture2 = THREE.ImageUtils.loadTexture('img/caby.jpg', {}, render);//caby
        // var texture1 = new THREE.TextureLoader().load('img/rack_panel.jpg');//机柜外表贴图纹理
        // var texture3 = new THREE.TextureLoader().load('img/cabz.jpg');//cabz
        // var texture2 = new THREE.TextureLoader().load('img/caby.jpg');//caby

        // 创建组合对象
        var cabGroup = new THREE.Group();
        //cabGroup的平面中心是机柜主体的平面中心
        cabGroup.position.set(this.x,this.y,this.z);
        cabGroup.name = 'cabGroup';


        var cabMatLambert = new THREE.MeshLambertMaterial({//设置朗伯材质和贴图
            color:0x8E8E8E,
            map:texture1
        });
        var cabMatBasic = new THREE.MeshBasicMaterial({//设置基础材质和贴图
            color:0x8E8E8E,
            map:texture1
        });
        
        // 创建一个三维立方体几何体
        // 想象人站在机柜中面朝机柜门的底部立方体（机柜主体底部立方体） 宽30，高2，长40
        var cabBottomGeo = new THREE.BoxGeometry(dk,2,dc);
        var cabBottomMaterials = [];
        //push顺序：X轴正、反，Y轴正、反，Z轴正、反
        cabBottomMaterials.push(
            cabMatBasic,
            cabMatBasic,
            new THREE.MeshBasicMaterial({
                color:0xBEBEBE,
                map:texture2
            }),
            cabMatBasic,
            cabMatBasic,
            cabMatBasic
        );
        // 面材质，可以为几何体的每个面指定不同的材质
        var cabBottomMat = new THREE.MeshFaceMaterial(cabBottomMaterials);
        // var cabBottom = new THREE.Mesh(cabBottomGeo,cabMatBasic);
        var cabBottom = new THREE.Mesh(cabBottomGeo,cabBottomMat);
        cabBottom.position.set(0,1,0);

        // 创建一个三维立方体几何体
        // 想象人站在机柜中面朝机柜门的左侧部立方体 厚2，高88，长40
        var cabLeftGeo = new THREE.BoxGeometry(2,88,dc);
        var cabLeftMaterials = [];
        //push顺序：X轴正、反，Y轴正、反，Z轴正、反
        cabLeftMaterials.push(
            cabMatLambert,
            cabMatLambert,
            cabMatLambert,
            cabMatLambert,
            new THREE.MeshBasicMaterial({
                color:0xBEBEBE,
                map:texture2
            }),
            cabMatBasic
        );
        // 面材质，可以为几何体的每个面指定不同的材质
        var cabLeftMat = new THREE.MeshFaceMaterial(cabLeftMaterials);
        var cabLeft = new THREE.Mesh(cabLeftGeo,cabLeftMat);
        cabLeft.position.set(dk/2-1,46,0);

        // 创建一个三维立方体几何体
        // 想象人站在机柜中面朝机柜门的右侧部立方体 厚2，高88，长40
        var cabRightGeo = new THREE.BoxGeometry(2,88,dc);
        var cabRightMaterials = [];
        cabRightMaterials.push(
            cabMatLambert,
            cabMatBasic,
            cabMatLambert,
            cabMatLambert,
            new THREE.MeshBasicMaterial({
                color:0xBEBEBE,
                map:texture3
            }),
            cabMatBasic
        );
        var cabRightMat = new THREE.MeshFaceMaterial(cabRightMaterials);
        var cabRight = new THREE.Mesh(cabRightGeo,cabRightMat);
        cabRight.position.set(-dk/2+1,46,0);

        // 创建一个三维立方体几何体
        // 想象人站在机柜中面朝机柜门的后面那个立方体 宽26，高88，厚2
        var cabBehindGeo = new THREE.BoxGeometry(dk-4,88,2);
        var cabBehind = new THREE.Mesh(cabBehindGeo,cabMatBasic);
        cabBehind.position.set(0,46,0-dc/2+1);

        // 创建一个三维立方体几何体
        // 想象人站在机柜中面朝机柜门的顶部立方体（机柜主体顶部立方体） 
        var cabTopGeo = new THREE.BoxGeometry(dk,2,dc);
        var cabTopMaterials = [];
        cabTopMaterials.push(
            cabMatBasic,
            cabMatBasic,
            new THREE.MeshLambertMaterial({
                color:0x8E8E8E,
                map:cabinetNumberTexture(this.number)//canvas贴图
            }),
            cabMatLambert,
            cabMatLambert,
            cabMatLambert
        );
        var cabTopMat = new THREE.MeshFaceMaterial(cabTopMaterials);
        var cabTop = new THREE.Mesh(cabTopGeo,cabTopMat);
        cabTop.position.set(0,91,0);
        cabTop.name = 'cabs';


        // cabGroup不包括机柜门
        cabGroup.add(cabBottom,cabLeft,cabRight,cabBehind,cabTop);


        // // 创建机柜的门
        // var doorGroup = new THREE.Group();
        // doorGroup.position.set(this.x+dk/2,this.y,this.z+dc/2);
        // doorGroup.name = this.number;//机柜门的名字为输入的编号

        // var doorGeo = new THREE.BoxGeometry(dk,92,1);//机柜门宽，高，厚
        // var doorMaterials = [];
        // doorMaterials.push(
        //     new THREE.MeshLambertMaterial({color:0x999999}),
        //     new THREE.MeshLambertMaterial({color:0x999999}),
        //     new THREE.MeshLambertMaterial({color:0x999999}),
        //     new THREE.MeshLambertMaterial({color:0x999999}),
        //     new THREE.MeshLambertMaterial({
        //         map:THREE.ImageUtils.loadTexture( 'img/rack_front_door.jpg', {}, render ),
        //         // map:new THREE.TextureLoader().load( 'img/rack_front_door.jpg' ),
        //         overdraw:true
        //     }),
        //     new THREE.MeshBasicMaterial({
        //         map:THREE.ImageUtils.loadTexture( 'img/rack_door_back.jpg', {}, render ),
        //         // map:new THREE.TextureLoader().load( 'img/rack_door_back.jpg' ),
        //         overdraw:true
        //     })
        // );
        // var doorMat = new THREE.MeshFaceMaterial(doorMaterials);
        // var door = new THREE.Mesh(doorGeo,doorMat);
        // door.name='door';
        // door.position.set(-dk/2,46,.5);
        // doorGroup.add(door);

        // scene.add(cabGroup,doorGroup);

        scene.add(cabGroup);
    }
    // 创建机柜中的服务器
    // 构造服务器 参数：obj所属机柜（如cab1）,h高度坐标 ,serverType服务器类型(两层的服务器serverType=2 or 三层的服务器serverType=3)
    function Server(obj,h,serverType=2){
        this.x = obj.x;
        this.y = 0;
        this.z = obj.z;
        this.h = h;

        var serverGroup = new THREE.Group();
        serverGroup.position.set(this.x ,this.y,this.z);

        //两层的服务器 or 三层的服务器
        var serverHeight = 2*parseInt(serverType);
        var serverGeo = new THREE.BoxGeometry(24,serverHeight-0.5,36-0.2);//这里服务器的尺寸要跟机柜尺寸对应好
        var serverMat = new THREE.MeshBasicMaterial({
            color:0x9AC0CD,
            map:THREE.ImageUtils.loadTexture('img/rack_inside.jpg', {}, render),
            // map:new THREE.TextureLoader().load('img/rack_inside.jpg'),
        });
        var serverMain = new THREE.Mesh(serverGeo,serverMat);//服务器主体
        serverMain.position.set(0,this.h,2-0.2);

        var serverFaceGeo = new THREE.BoxGeometry(26,serverHeight,0.2);//服务器面板尺寸
        var serverFaceMaterials = [];
        serverFaceMaterials.push(
            new THREE.MeshBasicMaterial({color:0xffffff}),
            new THREE.MeshBasicMaterial({color:0xffffff}),
            new THREE.MeshBasicMaterial({color:0xffffff}),
            new THREE.MeshBasicMaterial({color:0xffffff}),
            new THREE.MeshBasicMaterial({
                map:THREE.ImageUtils.loadTexture(`img/server${serverType}.jpg`,{},render),
                // map:new THREE.TextureLoader().load(`img/server${serverType}.jpg`),
                overdraw:true
            }),
            new THREE.MeshBasicMaterial({color:0xffffff})
        );
        var serverFaceMat = new THREE.MeshFaceMaterial(serverFaceMaterials);//服务器面板材质
        var serverFace = new THREE.Mesh(serverFaceGeo,serverFaceMat );
        serverFace.name= `server${serverType}`;
        serverFace.position.set(0,this.h,40/2-0.2/2); // 36/2+2-0.2/2
        serverGroup.add(serverMain,serverFace);

        scene.add(serverGroup);
    }
    // 创建机柜中的交换机
    // 构造交换机 参数：obj所属机柜（如cab1）,h高度坐标
    function Switch(obj,h){
      this.x = obj.x;
      this.y = 0;
      this.z = obj.z;
      this.h = h;

      var switchHeight = 12;
      var switchGroup = new THREE.Group();
      switchGroup.position.set(this.x,this.y,this.z);
      var switchTexture = THREE.ImageUtils.loadTexture('img/rack_inside.jpg', {}, render);
      // var switchTexture = new THREE.TextureLoader().load('img/rack_inside.jpg');
      var switchMainGeo = new THREE.BoxGeometry(24,switchHeight-0.5,36-0.2);//交换机主体尺寸，宽厚长，要跟机柜对应
      var switchMainMat = new THREE.MeshBasicMaterial({
          color:0x9AC0CD,
          map:switchTexture
      });
      var switchMain = new THREE.Mesh(switchMainGeo,switchMainMat);
      switchMain.position.set(0,this.h,2-0.2);

      var switchFaceGeo = new THREE.BoxGeometry(26,switchHeight,0.2);//交换机面板尺寸
      var switchFaceMat = new THREE.MeshBasicMaterial({//交换机面板材质
          color:0xffffff
      });
      var switchFaceMaterials = [];
      switchFaceMaterials.push(
        switchFaceMat,
        switchFaceMat,
        switchFaceMat,
        switchFaceMat,
        new THREE.MeshBasicMaterial({
            map:THREE.ImageUtils.loadTexture('img/switch.jpg', {}, render),
            // map:new THREE.TextureLoader().load('img/switch.jpg'),
            overdraw:true
        }),
        switchFaceMat
      );
      var switchFaceMat = new THREE.MeshFaceMaterial(switchFaceMaterials);//交换机面板材质
      var switchFace = new THREE.Mesh(switchFaceGeo,switchFaceMat);
      switchFace.position.set(0,this.h, 40/2-0.2/2); // 36/2+2-0.2/2
      switchGroup.add(switchMain,switchFace);

      scene.add(switchGroup);
    }
    // 创建火焰
    // 构造火焰 参数：obj所属机柜（如cab1）
    function Flame(obj) {
      this.x = obj.x;
      this.y = 88;
      this.z = obj.z;

      // 初始化一个空容器，装载粒子
      var krq = new THREE.Object3D();
      krq.position.set(this.x ,this.y-5,this.z);
      // sprite材质
      var material = new THREE.SpriteMaterial({
        //以canvas作为纹理
        map: THREE.ImageUtils.loadTexture('img/flamex.png', {}, render),
        // map: new THREE.TextureLoader().load("img/flamex.png"),
        //混合度 加法混合
        blending: THREE.AdditiveBlending
      });

      //循环2000  添加粒子
      for (var i = 0; i < 2000; i++) {
        var particle = new THREE.Sprite(material);
        initParticle(particle, i);
        krq.add(particle);
        krq.name = "particles_flame";
      }

      scene.add(krq);
    }
    /**
      * 粒子 延迟发散
      * @param particle
      * @param delay
      */
    function initParticle(particle, delay) {
      particle.position.set(0, Math.random() + 12, 0);
      particle.scale.x = particle.scale.y = Math.random() * 13;
      //下面是一系列的动画
      var xx = Math.random() * 40 - 20;
      var yy = Math.cos((Math.PI / 100) * xx) * 80;
      //位移
      new TWEEN.Tween(particle.position)
        .delay(delay)
        .to({
          x: xx,
          y: yy,
          z: Math.random() * 40 - 20
        }, 2000)
        .onComplete(function() {
          initParticle(particle, delay);
        })
        .start();
      // 大小
      new TWEEN.Tween(particle.scale)
        .delay(delay)
        .to({
          x: 0.01,
          y: 0.01
        }, 1000)
        .start();
    }

    

    // 创建对象
    function createObject() {
      new Floor();

      var cab11 = new Cabinet(-100,100,'1A01');
      // 往cab11机柜里加个服务器
      var server1 = new Server(cab11,50,2); // 高度需要通过计算对应好
      var server2 = new Server(cab11,4,2);
      var server3 = new Server(cab11,20,3);
      // 往cab11机柜里加个交换机
      var switch1 = new Switch(cab11,70);

      // 可以继续添加机柜
      // var cab12 = new Cabinet(-100,0,'1A02');
      // var cab13 = new Cabinet(-100,-100,'1A03');

      // var cab21 = new Cabinet(100,100,'2A01');
      // var cab22 = new Cabinet(100,0,'2A02');
      // var cab23 = new Cabinet(100,-100,'2A03');

      var cab12 = new Cabinet(-50,100,'1A02');
      // 往cab12机柜里加个火焰
      var flame1 = new Flame(cab12);
      var cab13 = new Cabinet(50,100,'1A03');
      var cab14 = new Cabinet(100,100,'1A04');

      var cab21 = new Cabinet(-100,-50,'2A01');
      var cab22 = new Cabinet(-50,-50,'2A02');
      var cab23 = new Cabinet(50,-50,'2A03');
      var cab24 = new Cabinet(100,-50,'2A04');
    }


    // 视角控制器
    var controls;
    function createControls(){
        controls = new THREE.OrbitControls(camera);
        controls.addEventListener('change',render);
        //相机到原点的最远距离
        controls.maxDistance = 2000;
    }
    // createControls();

    // 渲染
    function render(){
        TWEEN.update();
        renderer.clear();

        // 使用requestAnimationFrame函数进行渲染
        requestAnimationFrame(render);

        renderer.render(scene,camera);
    }
    // render();

    // 事件
    function onDocumentMouseDown(event) {
        event.preventDefault();
        //1、先基于我们在屏幕上点击的位置创建一个向量
        var vector = new THREE.Vector3(
            (event.clientX / window.innerWidth ) * 2 - 1,
            -( event.clientY / window.innerHeight ) * 2 + 1,
            0.5
        );
        //2、然后用unproject函数将点击位置转换成Thres.js场景中的坐标
        vector = vector.unproject(camera);
        //3、用THREE.Raycaster对象向点击位置发射光线
        var raycaster = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize());
        //4、计算射线相机到的对象，可能有多个对象，因此返回的是一个数组，按离相机远近排列
        //将射线投影到屏幕，如果scene.children里的某个或多个形状相交，则返回这些形状
        //第二个参数是设置是否递归，默认是false，也就是不递归。当scene里面添加了Group对象的实例时，就需要设置这个参数为true
        //第一个参数不传scene.children也可以，传一个group.children或一个形状数组都可以（这样可以实现一些特别的效果如点击内部的效果）
        //另外，因为返回的是一个数组，所以遍历数组就可以获得所有相交的对象，当元素重叠时，特别有用
        var intersects = raycaster.intersectObjects(scene.children,true);
        var currObj = intersects[0].object;//currObj为点击到的第一个对象

        //如果这个对象是门
        //如果门是关闭的；那么打开，并且移动摄像机位置
        //如果门是打开的；那么关闭
        if(currObj.name=='door'){
            // console.log(currObj.parent.name);//currObj.parent是menGroup
            var p1=new THREE.Vector3(currObj.parent.position);//
            var number = currObj.parent.name;

            if(currObj.parent.rotation.y == 0){
                // console.error('open');
                new TWEEN.Tween( currObj.parent.rotation ).to({
                    y: .6*Math.PI
                }, 1500 ).easing( TWEEN.Easing.Elastic.Out).start();
                // console.log(currObj.parent.position);


                controls.target=new THREE.Vector3(
                    currObj.parent.position.x,
                    currObj.parent.position.y+50,
                    currObj.parent.position.z
                );
                // 移动相机的位置(有动画)，有问题解决待
                // new TWEEN.Tween( camera.position ).to({
                //     x:currObj.parent.position.x+15,
                //     y:currObj.parent.position.y+100,
                //     z:currObj.parent.position.z+130
                // }, 500).start();
                camera.position.set(
                    currObj.parent.position.x+15,
                    currObj.parent.position.y+100,
                    currObj.parent.position.z+130
                );
            }else{
                // console.error('close');
                new TWEEN.Tween( currObj.parent.rotation ).to({
                    y:0
                }, 300 ).start();

                // 关闭机柜门时，回到最初
                controls.target=new THREE.Vector3(0,0,0);
                // 移动相机的位置(有动画)，有问题解决待
                // // 设置相机的位置坐标
                // new TWEEN.Tween( camera.position ).to({
                //   x:0,
                //   y:150,
                //   z:300
                // }, 500).start();
                camera.position.set(0,150,300);
            }
            controls.update();
        }

        if(currObj.name=='server2' || currObj.name=='server3'){
            // console.error(currObj.parent.position.z);
            var p1=new THREE.Vector3(currObj.parent.position);

            if(currObj.parent.position.z == 100){
                new TWEEN.Tween( currObj.parent.position ).to({
                    z:currObj.parent.position.z+20
                }, 500 ).easing( TWEEN.Easing.Elastic.Out).start();
                // console.log(currObj.parent.position);
            }else{
                new TWEEN.Tween( currObj.parent.position ).to({
                    z:currObj.parent.position.z-20
                }, 500 ).easing( TWEEN.Easing.Elastic.Out).start();
            }
            controls.update();
        }

        render();
    }
    
    // 浏览器大小变化时
    function onResize() {
        // aspect表示屏幕长宽比
        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();
        renderer.setSize(window.innerWidth, window.innerHeight);
    }

    // 初始化
    function init() {
      initThree();

      createObject();

      document.addEventListener('dblclick', onDocumentMouseDown, false);
      
      // 创建控件对象
      createControls();  
      // 渲染
      render();

			// 监听窗体调整大小事件
      window.addEventListener('resize', onResize, false);
    }
    window.onload = init;
    // init();
</script>

</body>
</html>